package com.wejoy.video.middle.station.data.generator;


import com.wejoy.video.middle.station.data.generator.domain.ConnectInfo;
import com.wejoy.video.middle.station.data.generator.domain.DoMain;
import com.wejoy.video.middle.station.data.generator.domain.DoMainProperty;
import com.wejoy.video.middle.station.data.generator.domain.FileInfo;
import com.wejoy.video.middle.station.data.generator.util.JDBCUtil;
import com.wejoy.video.middle.station.data.generator.util.StringUtil;
import org.apache.commons.lang3.StringUtils;
import org.junit.jupiter.api.Test;

import java.io.File;
import java.util.*;

/**
 * 自动在com.xxx.entity.后追加。
 * <P>如：设置为equip，则会在com.xxx.domain.equip包下生成实体类
 * <P>其他文件类似，具体可以参考genConnectInfo方法中的设置
 * <P>多级目录用.分割，如： a.b.c.  则会在com.xxx.domain.a.b.c包下生成实体类
 * <P>实体类的类名根据表名生成。如：generator_test，则实体类名：GeneratorTest
 */
public class Generator {
    /////////////////////////////////////一般只需修改下面两个参数/////////////////////////////////////////////
    /**
     * todo 修改包名 todo 修改包名 todo 修改包名
     */
    private static final String PACKAGE = "alarm";

    /**
     * todo 修改表名 todo 修改表名 todo 修改表名
     */
    private static final String TABLE_NAME = "alarm_details";
    /**
     * 生成器类型 mysql es
     * TODO 注意在这里放开下面注释
     */
    private static final String GENERATOR_TYPE = "mysql";
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////


    //sql1获取表信息： 第一列：表名，第二列：表注释
    private static String sql_table;
    //sql2获取字段信息： 第一列：字段名称，第二列：字段注释，第三列：字段类型，第四列：varchar长度，第五列：是否可空
    private static String sql_fields;
    //本地工程目录,如果不设置，则根据默认的target目录，来生成
    private static String projectPath;
    //允许的数据库类型及映射关系
    private static Map<String, String[]> dataTypeMap;

    static {
        //有序
        dataTypeMap = new LinkedHashMap<>();
        //mysql
        dataTypeMap.put("varchar", new String[]{"String", "VARCHAR"});
        dataTypeMap.put("text", new String[]{"String", "VARCHAR"});
        dataTypeMap.put("datetime", new String[]{"Date", "TIMESTAMP"});
        dataTypeMap.put("double", new String[]{"Double", "DOUBLE"});
        dataTypeMap.put("int", new String[]{"Integer", "INTEGER"});
        dataTypeMap.put("bigint", new String[]{"Long", "BIGINT"});
        dataTypeMap.put("time", new String[]{"LocalTime", "TIMESTAMP"});
        dataTypeMap.put("decimal", new String[]{"BigDecimal", "DECIMAL"});
        dataTypeMap.put("date", new String[]{"Date", "TIMESTAMP"});
        dataTypeMap.put("tinyint", new String[]{"Boolean", "TINYINT"});
        dataTypeMap.put("bit", new String[]{"Integer", "INTEGER"});
    }

    @Test
    public void test() throws Exception {

        DoMain doMain = new DoMain();
        doMain.setGeneratorType(GENERATOR_TYPE);
        JDBCUtil jdbcUtil = new JDBCUtil(genConnectInfo(doMain));
        List<List<String>> executeSQL;
        //第一次查询表信息
        executeSQL = jdbcUtil.executeSQL(sql_table);

        for (List<String> list : executeSQL) {
            //0 名称
            doMain.setClassName(StringUtil.getClassName(list.get(0)));
            doMain.setNickName(StringUtil.makeFirstCharLow(doMain.getClassName()));
            //1 注释
            String tableNote = list.get(1);
            if (StringUtils.isEmpty(tableNote)) {
                throw new Exception("表注释不能为空");
            }
            doMain.setClassNote(tableNote);
            doMain.setTableName(TABLE_NAME);
        }
        //第二次查询字段信息
        executeSQL = jdbcUtil.executeSQL(sql_fields);
        jdbcUtil.closeConnection();

        //检查主键
        StringUtil.checkPrimaryKey(executeSQL.get(0), doMain.getOracle());
        //获取主键类型
        doMain.setIdJavaType(StringUtil.getPrimaryKeyType(executeSQL.get(0), doMain.getOracle()));

        List<DoMainProperty> doMainProperties = new ArrayList<>();
        for (List<String> list : executeSQL) {
            DoMainProperty doMainProperty = new DoMainProperty();
            //0 名称
            String colName = list.get(0);
            doMainProperty.setColumnName(colName);
            doMainProperty.setPropertyName(StringUtil.initCap(colName));
            //1 注释
            String columnNote = list.get(1);
            if (StringUtils.isEmpty(columnNote)) {
                throw new Exception(colName + "的字段注释不能为空");
            }
            doMainProperty.setColumnNote(columnNote);
            doMainProperty.setTerProperty(StringUtil.makeFirstCharUp(doMainProperty.getPropertyName()));
            //2 类型
            String columnType = list.get(2);
            for (String key : dataTypeMap.keySet()) {
                if (columnType.startsWith(key)) {
                    doMainProperty.setJavaType(dataTypeMap.get(key)[0]);
                    doMainProperty.setJdbcType(dataTypeMap.get(key)[1]);
                }
            }
            if (StringUtils.isEmpty(doMainProperty.getJavaType())
                    && StringUtils.isEmpty(doMainProperty.getJdbcType())) {
                throw new Exception(colName + "的数据库类型错误，请参照《开发规范》");
            }
            //3字符串长度
            String stringMaxLength = list.get(3);
            if (StringUtils.isNotEmpty(stringMaxLength)) {
                doMainProperty.setStringMaxLength(Integer.valueOf(stringMaxLength));
            }
            //4是否可空
            doMainProperty.setNullAble(true);
            if (list.get(4).startsWith("N")) {
                doMainProperty.setNullAble(false);
            }


            doMainProperties.add(doMainProperty);
        }
        doMain.setDoMainProperties(doMainProperties);

        if (StringUtils.isEmpty(projectPath)) {
            projectPath = new File(Generator.class.getResource("/").toURI()).getParentFile().getParentFile().getPath();
        }
        genFiles(doMain, projectPath);

        System.exit(0);
    }

    /**
     * 生成连接信息
     *
     * @param doMain doMain
     * @return ConnectInfo
     * @throws Exception Exception
     */
    private static ConnectInfo genConnectInfo(DoMain doMain) throws Exception {
        if (StringUtil.isMysql(TABLE_NAME)) {
            doMain.setOracle(false);
        } else {
            doMain.setOracle(true);
        }
        //各种包名
        StringBuilder daoPackage = new StringBuilder("com.wejoy.video.middle.station.data.mapper");
        StringBuilder esPackage = new StringBuilder("com.wejoy.video.middle.station.data.es");
        StringBuilder mapperPackage = new StringBuilder("mybatis");
        StringBuilder domainPackage = new StringBuilder("com.wejoy.video.middle.station.data.domain");
        StringBuilder servicePackage = new StringBuilder("com.wejoy.video.middle.station.data.service");
        StringBuilder controllerPackage = new StringBuilder("com.wejoy.video.middle.station.admin.controller");
        if (StringUtils.isEmpty(PACKAGE)) {
            throw new Exception("包名不能为空");
        }
        ConnectInfo connectInfo = new ConnectInfo();
        //数据库名称
        String DBName = "shanghairanqi-gas";
        String url = "jdbc:mysql://rm-y4mp9gof.mysql.rds.aliyuncs.com:3306/shanghairanqi-gas?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&zeroDateTimeBehavior=convertToNull";
        //查询准备
        connectInfo.setClassPath("/mysql-connector-java-6.0.6.jar");
        connectInfo.setDriverClass("com.mysql.jdbc.Driver");
        connectInfo.setUrl(url);
        connectInfo.setUserName("wjzp");
        connectInfo.setPassword("Wjzprdsmetoo123");

        sql_table = "select table_name,table_comment from information_schema.TABLES " +
                "where table_schema = '" + DBName + "' and table_name='" + TABLE_NAME + "'";
        sql_fields = "select column_name,column_comment,column_type,character_maximum_length,is_nullable " +
                "from information_schema.COLUMNS where table_schema = '" + DBName + "' and table_name='" +
                TABLE_NAME + "' ORDER BY ordinal_position ASC";
        //设置对应包名
        daoPackage.append(".").append(PACKAGE);
        mapperPackage.append(".").append(PACKAGE);
        esPackage.append(".").append(PACKAGE);
        domainPackage.append(".").append(PACKAGE);
        servicePackage.append(".").append(PACKAGE);
        controllerPackage.append(".").append(PACKAGE);

        doMain.setPackageName(domainPackage.toString());
        doMain.setSimplePackageName(PACKAGE);
        doMain.setDaoPackageName(daoPackage.toString());
        doMain.setEsPackageName(esPackage.toString());
        doMain.setMapperPackageName(mapperPackage.toString());
        doMain.setServicePackageName(servicePackage.toString());
        doMain.setControllerPackageName(controllerPackage.toString());
        return connectInfo;
    }

    /**
     * 生成对应的文件
     *
     * @param doMain      vm参数信息
     * @param projectPath 工程目录
     * @throws Exception Exception
     */
    private static void genFiles(DoMain doMain, String projectPath) throws Exception {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("doMain", doMain);

        //实体类
        FileInfo fileInfo = new FileInfo();
        fileInfo.setTargetProject(projectPath + "/src/main/java");
        fileInfo.setTargetPackage(doMain.getPackageName().toLowerCase());
        StringUtil.genTemplateFile("DoMain.vm", paramMap, fileInfo.toString() + "/" + doMain.getClassName() + ".java", true);
//        DAO接口
        fileInfo.setTargetProject(projectPath + "/src/main/java");
        fileInfo.setTargetPackage(doMain.getDaoPackageName().toLowerCase());
        StringUtil.genTemplateFile("IDao.vm", paramMap, fileInfo.toString() + "/I" + doMain.getClassName() + "Mapper.java");

        if ("mysql".equalsIgnoreCase(GENERATOR_TYPE)) {
            //mapper
            fileInfo.setTargetProject(projectPath + "/src/main/resources");
            fileInfo.setTargetPackage("/mybatis/");
            StringUtil.genTemplateFile("Mapper.vm", paramMap, fileInfo.toString() + "/" + doMain.getNickName() + "Mapper.xml", true);
        }

//        Service
        fileInfo.setTargetProject(projectPath + "/src/main/java");
        fileInfo.setTargetPackage(doMain.getServicePackageName().toLowerCase());
        StringUtil.genTemplateFile("IService.vm", paramMap, fileInfo.toString() + "/I" + doMain.getClassName() + "Service.java");
//        Service impl
        StringUtil.genTemplateFile("IServiceImpl.vm", paramMap, fileInfo.toString() + "/impl/" + doMain.getClassName() + "ServiceImpl.java");


        // Controller
        fileInfo.setTargetProject(new File(projectPath).getParentFile() + "/admin/src/main/java");
        fileInfo.setTargetPackage(doMain.getControllerPackageName().toLowerCase());
        StringUtil.genTemplateFile("Controller.vm", paramMap, fileInfo.toString() + "/" + doMain.getClassName() + "Controller.java");
////        // List vue
//        StringUtil.genTemplateFile("List.vm", paramMap, fileInfo.toString() + "/" + doMain.getNickName() + "List.vue");

    }
}
